package io.xxx.omni.sync.impl

import com.alibaba.fastjson.JSON
import com.jd.open.api.sdk.request.JdRequest
import com.jd.open.api.sdk.request.refundapply.PopAfsSoaRefundapplyQueryPageListRequest
import com.jd.open.api.sdk.request.supplier.DropshipDpsSearchRequest
import com.jd.open.api.sdk.request.supplier.DropshipDpsSearchpreRequest
import com.jd.open.api.sdk.response.AbstractResponse
import io.xxx.omni.sync.Document
import io.xxx.omni.sync.PagePorter
import io.xxx.omni.sync.Porter
import io.xxx.omni.sync.Store
import io.xxx.omni.util.dateTimeFormatter
import io.xxx.omni.util.toDate
import io.xxx.omni.util.toJSONObject
import io.xxx.omni.util.toLocalDateTime
import org.springframework.stereotype.Component
import org.springframework.util.ObjectUtils
import org.springframework.web.util.UriComponentsBuilder
import java.net.URI
import java.time.LocalDateTime

/**
 * 京东
 */
abstract class JdPorter : PagePorter() {

    val httpUrl = "http://114.67.201.245:3389/api/execute"

    protected inline fun <reified R : AbstractResponse> getResponse(store: Store, request: JdRequest<R>): R {
        val url = UriComponentsBuilder.fromHttpUrl(httpUrl)
            .queryParam("storeCode", store.code)
            .queryParam("requestClass", request.javaClass.name)
            .toUriString()
        val response = restTemplate.postForObject(url, request, R::class.java)
        if (!ObjectUtils.nullSafeEquals(response?.code, "0")) {
            throwException(request.apiMethod, response?.code, response?.msg)
        }
        return response!!
    }
}

@Component
class JdTradePorter : Porter() {

    private val httpUrl = "http://114.67.201.245:3389/api/orders/stream"

    override val platformCode = "jingdong"

    override val jobId = 1

    override fun getUrl(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): URI {
        return UriComponentsBuilder.fromHttpUrl(httpUrl)
            .queryParam("startTime", startTime.format(dateTimeFormatter))
            .queryParam("endTime", endTime.format(dateTimeFormatter))
            .queryParam("storeCode", store.code)
            .build(false)
            .toUri()
    }

    override fun buildDocuments(data: List<String>): List<Document> {
        return data.map {
            val value = JSON.parseObject(it)
            val modified = value.getString("modified").toLocalDateTime()
            Document(value.getString("orderId"), value, modified)
        }
    }
}

@Component
class JdRefundPorter : JdPorter() {

    override val platformCode = "jingdong"

    override val jobId = 2

    override val pageSize = 50

    override fun getCount(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): Long? {
        val request = buildRequest(startTime, endTime)
        val response = getResponse(store, request)
        return response.queryResult.totalCount
    }

    override fun getData(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Long,
    ): List<Document>? {
        val request = buildRequest(startTime, endTime, pageNo.toInt())
        val response = getResponse(store, request)
        val result = response.queryResult.result
        if (result.isNullOrEmpty()) {
            return emptyList()
        }
        return result.map {
            val modified = it.checkTime.toLocalDateTime() ?: it.applyTime.toLocalDateTime()
            Document(it.id.toString(), it.orderId.toString(), it.toJSONObject(), modified)
        }
    }

    private fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Int = 1
    ): PopAfsSoaRefundapplyQueryPageListRequest {
        val request = PopAfsSoaRefundapplyQueryPageListRequest()
        request.pageIndex = pageNo
        request.pageSize = pageSize
        request.applyTimeStart = startTime.format(dateTimeFormatter)
        request.applyTimeEnd = endTime.format(dateTimeFormatter)
        return request
    }
}

/**
 * 京东自营
 */
@Component
abstract class JdZyPagePorter : JdPorter() {

    override val platformCode = "jingdong_ziying"

    protected final inline fun <reified T : JdRequest<*>> buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Int = 1
    ): T {
        val params = mapOf(
            "page" to pageNo,
            "pageSize" to pageSize,
            "beginDate" to startTime.toDate(),
            "endDate" to endTime.toDate()
        )
        return JSON.parseObject(JSON.toJSONString(params), T::class.java)
    }
}

@Component
class JdZyTradePorter : JdZyPagePorter() {

    override val jobId = 1

    override fun getCount(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): Long? {
        val request = buildRequest<DropshipDpsSearchRequest>(startTime, endTime)
        val response = getResponse(store, request)
        return response.searchResult?.recordCount?.toLong()
    }

    override fun getData(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Long,
    ): List<Document>? {
        val request = buildRequest<DropshipDpsSearchRequest>(startTime, endTime, pageNo.toInt())
        val response = getResponse(store, request)
        val result = response.searchResult.resultDtoList
        return result?.map {
            Document(it.customOrderId.toString(), it.toJSONObject(), it.orderCreateDate.toLocalDateTime())
        }
    }
}

@Component
class JdZyRefundPorter : JdZyPagePorter() {

    override val jobId = 2

    override fun getCount(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): Long? {
        val request = buildRequest<DropshipDpsSearchpreRequest>(startTime, endTime)
        val response = getResponse(store, request)
        return response.searchPreResult?.recordCount?.toLong()
    }

    override fun getData(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Long,
    ): List<Document>? {
        val request = buildRequest<DropshipDpsSearchpreRequest>(startTime, endTime, pageNo.toInt())
        val response = getResponse(store, request)
        val result = response.searchPreResult.resultDtoList
        return result?.map {
            Document(it.customOrderId.toString(), it.toJSONObject(), it.orderCreateDate.toLocalDateTime())
        }
    }
}